package org.takeback.chat.schedule;

import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.takeback.chat.entity.PcConfig;
import org.takeback.chat.entity.PcRateConfig;
import org.takeback.chat.entity.ProxyVote;
import org.takeback.chat.entity.PubConfig;
import org.takeback.chat.entity.PubUser;
import org.takeback.chat.utils.DateUtil;
import org.takeback.chat.utils.NumberUtil;
import org.takeback.dao.BaseDAO;

@Service
public class ProxySchedule {
	@Autowired
	BaseDAO dao;

	@Transactional
	public void work() {
		PubConfig pc = (PubConfig) this.dao.getUnique(PubConfig.class, "param", "water");
		Double rate = Double.valueOf(pc.getVal());
		if ((rate.doubleValue() <= 0.0D) || (rate.doubleValue() >= 1.0D)) {
			return;
		}
		Map<String, List<Double>> waterConfigs = getWaterConfig();
		Date startDate = getStartDate();
		Date endDate = getEndDate();
		String hql = "from PubUser where parent is not null and userType<>'9' ";
		List<PubUser> proxys = this.dao.findByHql(hql);
		for (PubUser u : proxys) {
			try {
				String countHql = "select coalesce(sum(inoutNum),0) from GcLotteryDetail where uid=:uid and createDate>:startDate and createDate<:endDate";
				List<Object> recCounts = this.dao.findByHql(countHql,
						ImmutableMap.of("uid", u.getId(), "startDate", startDate, "endDate", endDate));

				String pcCountHql = "select coalesce(sum(userInout),0) from PcGameLog where uid=:uid and openTime>:startDate and openTime<:endDate";
				List<Object> pcCounts = this.dao.findByHql(pcCountHql,
						ImmutableMap.of("uid", u.getId(), "startDate", startDate, "endDate", endDate));

				Double num = Double.valueOf(Double.valueOf(recCounts.get(0).toString()).doubleValue()
						+ Double.valueOf(pcCounts.get(0).toString()).doubleValue());
				if (num.doubleValue() < 0.0D) {
					PubUser p = (PubUser) this.dao.get(PubUser.class, u.getParent());
					ProxyVote v = new ProxyVote();
					v.setCacuDate(endDate);
					v.setLose(Double.valueOf(NumberUtil.round(Math.abs(num.doubleValue()))));
					v.setNickName(u.getUserId());
					v.setUid(u.getId());
					v.setVote(Double.valueOf(NumberUtil.round(Math.abs(num.doubleValue()) * rate.doubleValue())));
					v.setParentId(p.getId());
					v.setParentNickName(p.getUserId());
					String addHql = "update PubUser set money=coalesce(money,0) + :vote where id =:uid";
					int effected = this.dao.executeUpdate(addHql,
							ImmutableMap.of("vote",
									Double.valueOf(NumberUtil.round(Math.abs(num.doubleValue()) * rate.doubleValue())),
									"uid", p.getId()));
					if (effected == 1) {
						this.dao.save(ProxyVote.class, v);
					}
					Double pcWater = Double.valueOf(pcCounts.get(0).toString());
					if (pcWater.doubleValue() < 0.0D) {
						Long count = Long
								.valueOf(this.dao.count("select count(*) from PcGameLog where uid =:uid and status <>0",
										ImmutableMap.of("uid", u.getId())));
						Double waterMin = (Double) ((List) waterConfigs.get("w_min")).get(0);
						if (count.longValue() >= 1L) {
							Double water = getWater(waterConfigs, pcWater);
							if (water.doubleValue() > 0.0D) {
								this.dao.executeUpdate("update PubUser set money = money +:water where id =:uid",
										ImmutableMap.of("water", water, "uid", u.getId()));
							}
						}
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	private Double getWater(Map<String, List<Double>> confs, Double money) {
        if (money >= 0.0) {
            return 0.0;
        }
        money = Math.abs(money);
        Double water = 0.0;
        for (int i = 1; i <= confs.size(); ++i) {
            String key = "w_" + i;
            List<Double> l = confs.get(key);
            if (l == null) {
                return water;
            }
            if (money < l.get(0)) {
                break;
            }
            water = money * l.get(1) / 100.0;
        }
        return water;
	}

	@Transactional
	public Map<String, List<Double>> getWaterConfig() {
		Map<String, List<Double>> config = new HashMap();
		List<PcConfig> list = this.dao.findByHql("from PcConfig where param like 'w_%' order by id");
		for (PcConfig c : list) {
			config.put(c.getParam(), getValues(c.getVal()));
		}
		return config;
	}

	private List<Double> getValues(String text) {
		List<Double> res = new ArrayList();
		String pattern = "【[0-9]+】";
		Pattern p = Pattern.compile(pattern);
		Matcher m = p.matcher(text);
		while (m.find()) {
			res.add(Double.valueOf(m.group().replaceAll("[【】]", "")));
		}
		return res;
	}

	@Transactional(readOnly = true)
	public Map<String, List<PcRateConfig>> getPcRateConfigs() {
		Map<String, List<PcRateConfig>> rates = new HashMap();
		List<PcRateConfig> list = this.dao.findByHql("from PcRateConfig order by id, catalog ");
		for (PcRateConfig config : list) {
			List<PcRateConfig> prc = (List) rates.get(config.getCatalog());
			if (prc == null) {
				prc = new ArrayList();
				rates.put(config.getCatalog(), prc);
			}
			prc.add(config);
		}
		return rates;
	}

	private Date getStartDate() {
		Date d = DateUtil.getStartOfToday();
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.add(11, -19);
		return c.getTime();
	}

	private Date getEndDate() {
		Date d = DateUtil.getStartOfToday();
		Calendar c = Calendar.getInstance();
		c.setTime(d);
		c.add(11, 29);
		return c.getTime();
	}
}
